#!/usr/bin/python
# -*- coding: UTF-8 -*-

import generate_feature.preprocessing as pre
import regex as reg
import numpy as np
import pandas as pd
import itertools
import time
from scipy.stats import f_oneway
from collections import deque


def get_chars(data):
    """
    获取所有出现的字符
    :param data:
    :return:
    """
    all_chars = ''.join(data)
    chars = list(set(all_chars))
    chars.sort()  # give a fixed order for chars
    return chars


def statis_psi(str_pnts, proteins):
    """
    calculate the each str_pnt ratio in each protein
    :param str_pnts:
    :param proteins:
    :return:
    """
    if type(str_pnts) != list:
        str_pnts = [str_pnts]
    if type(proteins) != list:
        proteins = [proteins]

    psi = np.zeros((len(proteins), len(str_pnts)))
    for i, pro in enumerate(proteins):
        for j, spt in enumerate(str_pnts):
            pattern = reg.compile(spt)
            result = reg.findall(pattern, pro, overlapped=True)
            hits = len(result)
            psi[i, j] = hits
        loops = len(pro) - len(spt) + 1
        psi[i, ] = psi[i, ] / loops

    return psi


def grow_branch(prv_strs, Chars, orien):
    if type(prv_strs) != list:
        prv_strs = [prv_strs]
    strs_pnt = []
    if orien == 0:
        for temp_str in itertools.product(prv_strs, Chars):
            str_pnt = '%s%s' % (temp_str[0], temp_str[1])
            strs_pnt.append(str_pnt)
    elif orien == 1:
        for prv_str in prv_strs:
            str_pnt = '%s.' % prv_str
            strs_pnt.append(str_pnt)
    return strs_pnt


def get_feature_tree(data):
    chars = get_chars(data)

    queue = deque()
    level = 1
    queue.append((chars, level))

    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
    count = 0
    h = 2

    while queue and count < (2 ** h - 1):
        node, level = queue.popleft()
        if node:
            l_child = grow_branch(node, chars, orien=0)
            r_child = grow_branch(node, chars, orien=1)
            queue.append((l_child, level + 1))
            queue.append((r_child, level + 1))

            count += 1
            print('The %d node' % count)
            """2.只存左子树，且算一次存一次,以序列形式命名"""
            if count == 1 or count % 2 == 0:
                print("calculate the %d nodes psi" % count)
                psi = statis_psi(node, data)
                psi_df = pd.DataFrame(psi, columns=node)
                name = str(node[0]) + "_" + str(node[-1])
                psi_df.to_csv("./psi_result/" + name + ".csv", index=False)
                print("%s feature groups creating is done!" % name)
        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))

    print('node sum:', count)

    return


def f_eval(data):
    """
    # 建立one-way test ANOVA F值存储表
    :param data: 最后一列为label，前面都是特征
    :return: 各列特征的F值
    """

    dataT = data[data.label == 1]
    dataF = data[data.label == 0]
    cols = data.shape[1]
    x = []
    F = []
    for i in range(cols - 1):
        f = f_oneway(dataT.iloc[:, i], dataF.iloc[:, i])
        x.append(dataT.columns[i])
        F.append(f.statistic)
    F_eval = pd.DataFrame({'x': x, 'F': F})

    return F_eval


if __name__ == "__main__":
    p_path = "./bacteriophage/virion.txt"
    n_path = "./bacteriophage/non_virion.txt"

    data, label = pre.load_file(p_path, n_path)
    get_feature_tree(data)
